filetype plugin indent on         " 设置加载对应文件类型的插件

set nocompatible                  " 设置不兼容原始vi模式
set ignorecase                    " 搜索时忽略大小写
set smartcase                     " 搜索时有大写才大小写敏感
set hlsearch                      " 搜索高亮
set incsearch                     " 搜索时及时跳转
set nowrapscan                    " 搜索到头不自动折返再搜索
set nu                            " 显示当前行号
set rnu                           " 显示相对行号
set laststatus=2                  " 显示状态栏
set noshowmode                    " 不显示当前模式，Airline会显示
set noruler                       " 不显示光标当前位置，Airline会显示
set showcmd                       " 显示当前未完成命令的按键
set cmdheight=1                   " 设置命令行的高度
set lazyredraw                    " 关闭不必要的屏幕重绘
set wildmenu                      " 命令行补全文件名
set wildignorecase                " 补全忽略大小写
set showmatch                     " 左括号匹配，无则响铃
set matchtime=0                   " 括号匹配时间，单位0.1s
set nowrap                        " 长行超屏而非回绕
set linebreak                     " 回绕时避免断词
set scrolloff=1                   " 保持n行始终在光标之下或之上
set autochdir                     " 自动切换工作目录
set mouse=a                       " 启用鼠标
set ttimeoutlen=50                " 快捷键延迟
set whichwrap=<,>,[,]             " 允许插入模式与普通模式光标在从首尾跨行
set backspace=indent,eol,start    " 允许<BS>键在插入模式删除：行首空白符、换行符、进入插入模式时光标之前的字符
set virtualedit=block,onemore     " 光标可出现在无字符空间：块选取模式，其它模式最多只允许出现在最后一个字符之后的位置
set hidden                        " 切换tab时自动隐藏当前buffer
set foldmethod=syntax             " 设置折叠方式
set nofoldenable                  " 启动vim时不开启折叠
set autoindent                    " 基于上行的缩进
set tabstop=8                     " 默认的tab宽，不足则为空格
set softtabstop=4                 " 键入的tab宽
set shiftwidth=4                  " 缩进的tab宽
set expandtab                     " 用空格代替tab，:retab恢复本行
set path=/usr/include/c++/9.2.1,. " 设置PATH目录方便跳转
set list                          " 显示空白符
set listchars=tab:▸\ ,trail:·,extends:↷,precedes:↶      " 设置空白符如何显示

" 读取缓冲区时回到上次离开时的位置
autocmd BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif
" 读取vim命令行的输出到当前文件缓冲区
command! -nargs=* Rcmd :let tmp=<q-args> | put =execute(tmp)

"================================
" => 设置临时文件
"================================
set history=500
set viminfo='100,<50,s10,h
set viminfofile=~/.cache/vim/viminfo
set noswapfile
set nobackup
set undofile
set undodir=~/.cache/vim/undo

"================================
" => Buffer、Window、Tab 操作
"================================
nnoremap <silent> <space>n :bn<CR>
nnoremap <silent> <space>b :bp<CR>
nnoremap <silent> <c-w>x :bd<CR>
function! Jump(i) abort
    if winnr('$') >= a:i
        exe a:i . 'wincmd w'
    endif
endfunction
nnoremap <silent> <space>1 :call Jump(1)<CR>
nnoremap <silent> <space>2 :call Jump(2)<CR>
nnoremap <silent> <space>3 :call Jump(3)<CR>
nnoremap <silent> <space>4 :call Jump(4)<CR>
nnoremap <silent> <space>5 :call Jump(5)<CR>
nnoremap <silent> <space>6 :call Jump(6)<CR>
nnoremap <silent> <tab> :wincmd w<CR>
nnoremap <silent> <leader>n :tabnext<CR>
nnoremap <silent> <leader>b :tabprevious<CR>

"================================
" => 插入模式快捷键
"================================
inoremap <c-a> <c-c>^i
inoremap <c-e> <end>
inoremap <c-u> <c-c><right>d^i
inoremap <c-k> <c-c><right>d$i
inoremap <c-d> <c-c><right>10<c-e>i
inoremap <c-b> <c-c><right>10<c-y>i
inoremap <c-]> <c-c>%i

"================================
" => 命令模式快捷键
"================================
cnoremap <c-a> <c-b>

"================================
" => 可视模式快捷键
"================================
vnoremap <c-a> 0
vnoremap <c-e> $
vnoremap y "+y

"================================
" => 普通模式快捷键
"================================
nnoremap <silent> <c-d> 10<c-e>
nnoremap <silent> <c-b> 10<c-y>
nnoremap <silent> <c-a> ^
nnoremap <silent> <c-e> $
nnoremap <silent> , yl
nnoremap <silent> Y y$
nnoremap <silent> <c-y> gg"+yG<c-o><c-o>

" sudo写入文件
nnoremap <silent> <c-w>W :w !sudo tee % > /dev/null<CR>l<CR>

" 快速编辑宏，连按两次
nnoremap <leader>m  :<c-u><c-r><c-r>='let @'. v:register .' = '. string(getreg(v:register))<cr><c-f><left>

" 使用/与?搜索时n/N始终向下/上搜索
nnoremap <expr> n  'Nn'[v:searchforward]
nnoremap <expr> N  'nN'[v:searchforward]

" 快速添加空行
nnoremap <silent> <space>o  :<c-u>put =repeat(nr2char(10), v:count1)<CR><up>
nnoremap <silent> <space>O  :<c-u>put! =repeat(nr2char(10), v:count1)<CR><down>

" 关闭高亮
nnoremap <silent> <Leader>h :nohl<CR>

" 切换长行回绕是否断词
function! ToggleLinebreak()
    if &linebreak == 1
        setl nolinebreak
    else
        setl linebreak
    endif
endfunction
nnoremap <silent> <leader>l :call ToggleLinebreak<cr>

" 切换是否长行回绕
function! ToggleWrap()
    if &wrap == 1
        setl nowrap
    else
        setl wrap
    endif
endfunction
nnoremap <silent> <Leader>w :call ToggleWrap()<CR>

" 切换是否开启虚拟编辑，即光标能否出现在无字区域
function! ToggleVirtuledit()
    if &virtualedit =~ "all"
        setl virtualedit=block,onemore
    else
        setl virtualedit=all
    endif
endfunction
nnoremap <silent> <leader>v :call ToggleVirtuledit()<CR>

" 切换是否用空格代替制表符
function! ToggleExpandtab()
    if &expandtab == 1
        setl noexpandtab
    else
        setl expandtab
    endif
endfunction
nnoremap <silent> <leader>t :call ToggleExpandtab()<CR>

" 切换图形字符使用的宽度，双宽度可解决Gvim中Nerd图标字体只显示一半的情况，不过有时会影响其他字体的显示
function! ToggleAmbiwidth()
    if &ambiwidth == 'double'
        set ambiwidth=single
    else
        set ambiwidth=double
    endif
endfunction
nnoremap <silent> <leader>a :call ToggleAmbiwidth()<CR>

"================================================ 插件配置 ======================================================

"================================
" => Airline配置
"================================
let g:airline_theme="cool"                " AirlineTheme for Gvim
let g:airline_powerline_fonts = 1
let g:airline_detect_spell=0
let g:airline_extensions = ['branch', 'tabline', 'tagbar']

"================================
" => NERDTree配置
"================================
let NERDTreeMinimalUI=1
let NERDTreeWinPos='right'
let g:NERDTreeFileExtensionHighlightFullName = 1
let g:NERDTreeExactMatchHighlightFullName = 1
let g:NERDTreePatternMatchHighlightFullName = 1
let g:NERDTreeHighlightFolders = 1
let g:NERDTreeHighlightFoldersFullName = 1
" 按 <F3> 开关文件树
noremap <silent> <F3> :NERDTreeToggle<CR>:wincmd p<CR>

"================================
" => Tagbar配置
"================================
let g:tagbar_left=1
let g:tagbar_width = 30
" 按 <F2> 开关符号列表
noremap <silent> <F2> :TagbarToggle<CR>

"================================
" => Undotree配置
"================================
" 按 <F4> 开关可视化撤销树
nnoremap <silent> <F4> :UndotreeToggle<CR>

"================================
" => AutoPairs配置
"================================
" 自带的开关快捷键 <M-P> 在终端中用不了，再添加一个 <Leader>p
nnoremap <leader>p :call AutoPairsToggle()<CR>

"================================
" => Devicons配置
"================================
let g:webdevicons_enable_startify = 1
let g:webdevicons_enable_airline_tabline = 1
let g:webdevicons_enable_airline_statusline = 1
let g:webdevicons_enable_nerdtree = 1

"================================
" => IndentLine配置
"================================
let g:indentLine_fileType = ['c', 'cpp']

"================================
" => NERDCommenter配置
"================================
let g:NERDCreateDefaultMappings=0
" 按 <Leader>cc 快速 取消/注释 代码，按 <Leader>ca 快速在行尾添加注释
nmap <silent> <leader>cc <plug>NERDCommenterToggle
nmap <silent> <leader>ca <plug>NERDCommenterAppend

"================================
" => Instant-Markdown配置
"================================
" 使用命令 :InstantMarkdownPreview 开启Markdown即时预览，该插件会打开你的默认浏览器
let g:instant_markdown_autostart = 0

"================================
" => LeaderF配置
"================================
let g:Lf_WindowHeight = 0.2
let g:Lf_GtagsAutoGenerate = 1
let g:Lf_RootMarkers = ['.git', '.svn', '.root']    " 从当前目录递归向上查找这些文件，将此文件所在目录当作项目根目录并生成gtags
let g:Lf_WildIgnore = {
        \ 'dir': ['.svn', '.git'],
        \ 'file': ['.root', '*.bak', '*.save', '*.exe', '*.o', '*.so']
        \}
command! Csh :echo "PREFIX: \<space\>c
            \ \n s   symbol    ：查找该符号的引用
            \ \n g   global    ：查找该符号的定义
            \ \n a   assign    ：查找该符号被赋值的位置
            \ \n c   calls     ：查找调用当前函数的位置
            \ \n d   depends   ：查找当前函数调用的函数
            \ \n i   includes  ：查询引入了当前文件的文件
            \ \n f   file      ：打开文件名
            \ \n t   text      ：查找出现该字符串的位置
            \ \n e   egrep     ：使用 egrep 搜索当前单词
            \ \n 需要时请手动cs add <gtags_db_file>，此文件会由Leaderf自动生成在~/.LfCache/gtags/\%path\%to\%project\%root/GTAGS
            \"
command! Lfh :echo "PREFIX: \<space\>f
            \ \n f      ：搜索函数
            \ \n t      ：搜索符号
            \ \n z      ：搜索文件
            \ \n g      ：通过gtags搜索
            \ \n c      ：通过gtag的内容查找
            \ \n u      ：手动更新gtags
            \"
nnoremap <silent> <space>fh :Lfh<CR>
nnoremap <silent> <space>ff :Leaderf function --all<CR>
nnoremap <silent> <space>ft :Leaderf bufTag --all<CR>
nnoremap <silent> <space>fz :Leaderf <CR>
nnoremap <silent> <space>fg :Leaderf gtags<CR>
nnoremap <silent> <space>fc :Leaderf gtags --grep<CR>
nnoremap <silent> <space>fu :Leaderf gtags --update<CR>
nnoremap <silent> gr :Leaderf! gtags -r  <c-r>=expand('<cword>')<cr> --auto-jump<cr>
nnoremap <silent> gd :Leaderf! gtags -d  <c-r>=expand('<cword>')<cr> --auto-jump<cr>
nnoremap <silent> gs :Leaderf! gtags -s  <c-r>=expand('<cword>')<cr> --auto-jump<cr>
set cscopeprg=/usr/local/bin/gtags-cscope
set cscopequickfix=s-,c-,d-,i-,t-,e-,a-
set nocst
nnoremap <silent> <space>ch :Csh<cr>
nnoremap <silent> <space>ca :cscope find a  <c-r>=expand('<cword>')<cr><cr>
nnoremap <silent> <space>cg :cscope find g  <c-r>=expand('<cword>')<cr><cr>
nnoremap <silent> <space>cc :cscope find c  <c-r>=expand('<cword>')<cr><cr>
nnoremap <silent> <space>ct :cscope find t  <c-r>=expand('<cword>')<cr><cr>
nnoremap <silent> <space>ce :cscope find e  <c-r>=expand('<cword>')<cr><cr>
nnoremap <silent> <space>cf :cscope find f  <c-r>=expand('<cfile>')<cr><cr>
nnoremap <silent> <space>ci :cscope find i ^<c-r>=expand('<cfile>')<cr>$<cr>
nnoremap <silent> <space>cd :cscope find d  <c-r>=expand('<cword>')<cr><cr>

"================================
" => YCM配置
"================================
" 添加白名单，节省性能资源
let g:ycm_filetype_whitelist = {
        \ "c":1,
        \ "cpp":1,
        \ "vim":1,
        \ "sh":1,
        \ "zsh":1,
        \ }
" 两个字符便触发语义补全，由此导致Snips无法显示在补全列表
let g:ycm_semantic_triggers =  {
        \ 'c,cpp,sh': ['re!\w{2}'],
        \ }
let g:ycm_add_preview_to_completeopt = 0
set completeopt=menu,menuone
let g:ycm_use_clangd = 1
let g:ycm_show_diagnostics_ui = 0
let g:ycm_confirm_extra_conf=0
let g:ycm_cache_omnifunc=0
let g:ycm_seed_identifiers_with_syntax=1
let g:ycm_min_num_identifier_candidate_chars = 2
let g:ycm_complete_in_comments=0
let g:ycm_complete_in_strings=0
let g:ycm_collect_identifiers_from_comments_and_strings = 0
let g:ycm_collect_identifiers_from_tags_files = 0
let g:ycm_key_list_stop_completion = ['<CR>']
let g:ycm_key_invoke_completion = '<c-z>'   " 按 <C-Z> 手动触发语义补全
" gp 获取所在作用域，gt 获取目标类型，go 跳转定义
nnoremap gp :YcmCompleter GetParent<CR>
nnoremap gt :YcmCompleter GetType<CR>
nnoremap go :YcmCompleter GoTo<CR>

"================================
" => Cpp_Enhanced_Highlight配置
"================================
let g:cpp_class_scope_highlight = 1
let g:cpp_member_variable_highlight = 1
let g:cpp_class_decl_highlight = 1
let g:cpp_posix_standard = 1
let g:cpp_experimental_template_highlight = 1           " which is a faster implementation but has some corner cases where it doesn't work.
" let g:cpp_experimental_simple_template_highlight = 1  " which works in most cases, but can be a little slow on large files
" let g:cpp_concepts_highlight = 1
" let g:cpp_no_function_highlight = 1

"================================
" => UltiSnips配置
"================================
" 解决UltiSnips与YCM按键冲突网上有教程加两个函数与映射解决，我更愿意如此
" <M-Q> 触发UltiSnips补全，<M-B> 跳转上个位置，<M-M> 跳转下个位置
let g:UltiSnipsExpandTrigger = '<m-q>'
let g:UltiSnipsJumpBackwardTrigger = '<m-b>'
let g:UltiSnipsJumpForwardTrigger = '<m-m>'

"================================
" => Startify配置
"================================
let g:ascii = [
            \ '                                       ^   ',
            \ '                                _     /|   ',
            \ '                              _( \_/)/ /   ',
            \ '                              ,((((^/\/    ',
            \ '                              ((((  (*~\   ',
            \ '                           ,((((( ,     \  ',
            \ '        ,,,_              ,(((((  /"._  ,`,',
            \ '       ((((\\ ,...       ,((((   /    `-.-`',
            \ '       )))  ;`    `"`"`""((((   (          ',
            \ '     (((  /            ((       \          ',
            \ '      ((  |        .       "     \         ',
            \ '      ))  \     _ `      `t   ,.`)         ',
            \ '      (   |   y;- -,-""-"-.\   \/          ',
            \ '     )   / ./  ) /.         `\  \          ',
            \ '         |./   ( (           / /`          ',
            \ '         ||     \\          //`|           ',
            \ '         ||     _")       _//`||           ',
            \ '         ||    |_/       |_/  ||           ',
            \ '         \_\                  ||           ',
            \ '         ``"                  \_\          ',
            \ ]
let g:startify_custom_header =
          \ 'startify#pad(g:ascii + startify#fortune#boxed())'
function! StartifyEntryFormat()     " 开启devicons图标
    return 'WebDevIconsGetFileTypeSymbol(absolute_path) ." ". entry_path'
endfunction

"================================
" => 终端VIM的配置
"================================
if !has("gui_running")

    colorscheme ron
    let airline_theme='random'      " AirlineTheme for Vim

    " 插入模式与普通模式的光标形状切换
    let &t_SI = "\e[6 q"
    let &t_EI = "\e[2 q"
    " 其他选项（替换\ _ [后）的数字：
    " Ps = 0  -> blinking block.
    " Ps = 1  -> blinking block (default).
    " Ps = 2  -> steady block.
    " Ps = 3  -> blinking underline.
    " Ps = 4  -> steady underline.
    " Ps = 5  -> blinking bar (xterm).
    " Ps = 6  -> steady bar (xterm).

    " 写入vimrc时自动读取配置，增加++nested以解决Airline写回文件时导致的颜色失调问题，与Airline的random主题冲突
    " autocmd BufWritePost $MYVIMRC ++nested source $MYVIMRC

endif

"================================
" => vim-plug配置
"================================
call plug#begin('~/.vim/plugged')

Plug 'mhinz/vim-startify'                                                   " 无目标文件时vim的引导界面
Plug 'tpope/vim-fugitive'                                                   " 集成git到vim，我就只是想要个statuline图标 (0.0)~
Plug 'vim-airline/vim-airline'                                              " 状态栏与标签栏插件
Plug 'vim-airline/vim-airline-themes'                                       " 上述插件颜色主题
Plug 'preservim/nerdtree', { 'on':  'NERDTreeToggle' }                      " 显示文件层次结构，选择打开文件、切换目录
Plug 'tiagofumo/vim-nerdtree-syntax-highlight', { 'on':  'NERDTreeToggle' } " 上述插件的语法高亮增强
Plug 'mbbill/undotree', { 'on': 'UndotreeToggle' }                          " 撤销树可视化，引入分支的概念，类似git一样跳转
Plug 'majutsushi/tagbar', { 'on': 'TagbarToggle' }                          " 显示代码中所有的标识符（函数、类、类成员、宏之类的）
Plug 'ryanoasis/vim-devicons'                                               " 为其他插件提供文件类型图形符号，需要下载nerd字体
Plug 'kien/rainbow_parentheses.vim'                                         " 彩虹颜色显示嵌套括号
Plug 'jiangmiao/auto-pairs'                                                 " 自动补全结对符（括号、引号之类的）
Plug 'preservim/nerdcommenter'                                              " 快速注释或取消注释指定行数代码
Plug 'Yggdroot/indentLine'                                                  " 缩进线，增强代码缩进的视觉化
Plug 'vim-scripts/fcitx.vim'                                                " 若使用fcitx中文输入法框架，此插件会在离开插入模式进入普通模式时自动切换会英文输入法
Plug 'easymotion/vim-easymotion'                                            " 快速移动光标位置，例如输入指定搜索字符，该插件会将所有位置标志出来，按下显示的标志键快速跳转
Plug 'terryma/vim-multiple-cursors'                                         " 多光标编辑，一般用于重构，不过使用前应该先将ALE语法检测关闭，不然卡
Plug 'plasticboy/vim-markdown', { 'for': 'markdown' }                       " 对markdown的基本支持
" Plug 'suan/vim-instant-markdown', { 'for': 'markdown' }                   " 即时预览Markdown文件渲染结果，该插件存在一些依赖，可以安装AUR版本
Plug 'octol/vim-cpp-enhanced-highlight', { 'for': 'cpp' }                   " C++语言的语法高亮增强
Plug 'SirVer/ultisnips', { 'for': ['cpp', 'c', 'markdown', 'snippets'] }    " 根据输入的字符，自动补全完整代码，可以按snips的语法自己添加片段
Plug 'dense-analysis/ale', { 'on': [] }                                     " 动态语法检测，cppcheck和clangtidy的bug可以用仓库中vim/{clangtidy,cppcheck}.vim替换你的ale/ale_linters/cpp/{clangtidy,cppcheck}.vim
" Plug 'https://gitee.com/mirrors/youcompleteme.git'                        " 基于标签和语义的代码补全，该插件较大且需要手动编译安装，可以安装AUR版本
Plug 'Shougo/echodoc.vim', { 'for': ['c', 'cpp'] }                          " ycm补全函数后输入左括号则在原本命令行的位置显示函数参数提示
Plug 'Yggdroot/LeaderF', { 'do': './install.sh', 'on': 'Leaderf' }          " 工程项目快速搜索（文件、符号、跳转引用及定义），高级功能依赖gtags
Plug 'kana/vim-textobj-user'                                                " 此五个插件用于自定义文本对象，比如 dii 删除同缩进的代码，dif 删除函数内容，di, 删除函数参数
Plug 'kana/vim-textobj-syntax'
Plug 'kana/vim-textobj-indent'
Plug 'sgur/vim-textobj-parameter'
Plug 'kana/vim-textobj-function', { 'for':['c', 'cpp', 'vim'] }

" 以下是支持真色的颜色主题
Plug 'rakr/vim-one'
Plug 'drewtempelmeyer/palenight.vim'
Plug 'KeitaNakamura/neodark.vim'
Plug 'iCyMind/NeoSolarized'
Plug 'crusoexia/vim-monokai'
Plug 'morhetz/gruvbox'
Plug 'liuchengxu/space-vim-dark'
Plug 'lukelarsen/neospace-theme'

call plug#end()

"================================
" => Echodoc配置
"================================
let g:echodoc#enable_at_startup = 1

"================================
" => Easymotion配置
"================================
" 按 f{char}{char} 则显示所有{char}{char}所在位置，按 <Leader><Leader>l 快速跳转行
hi EasyMotionShade ctermbg=none ctermfg=grey
let g:EasyMotion_smartcase = 1
nmap f <Plug>(easymotion-overwin-f2)
nmap <leader><leader>l <Plug>(easymotion-overwin-line)

"================================
" => Multiple-cursor配置
"================================
" 按 <C-N> 选择单词，<C-X> 跳过选择该单词，<C-P> 选择上个单词，<Space>m 选择所有光标下的单词
" 选择完毕后即可如选择模式下一样对选中单词进行操作，注意要提前关闭ALE哦，不然卡的你怀疑人生
nnoremap <space>m :call multiple_cursors#select_all('n',1)<cr>

"================================
" => Rainbow-Parentheses配置
"================================
"更换主题会使其失效，:RainbowParenthesesActivate 开启
au VimEnter * RainbowParenthesesToggle
au Syntax * RainbowParenthesesLoadRound
au Syntax * RainbowParenthesesLoadSquare
au Syntax * RainbowParenthesesLoadBraces

"================================================ Gvim配置 ======================================================

if has("gui_running")

    set listchars=tab:▸\ ,trail:∙,eol:↵,extends:↷,precedes:↶    " 设置空白符如何显示
    set ambiwidth=double                                        " 解决devicon只显示一半图标的问题
    set gfn=Source\ Code\ Pro\ Black\ Italic\ 10                " 命令行输入 set gfn=* 打开系统字体选择面板
    set guioptions=agitd                                        " 不显示菜单，使用gui-dark-theme
    set guicursor=n:block,i:hor10,a:blinkon0                    " 设置光标状态
    set cursorline                                              " 高亮显示当前行
    set background=dark                                         " 设置主题被暗色

    colorscheme NeoSolarized
    " colorscheme   ：  NeoSolarized one palenight neodark gruvbox
    " airline_theme ：  atomic angr solarized solarized_flood cool one fruit_punch palenight base16_harmonic16 night_owl neodark behelit alduin gruvbox fairyfloss fruit_punch
    " 注意，Airline的atomic主题会改变状态栏格式，不喜欢的可以把源码中的第55行开始的那段代码注释

    " 切换窗口时自动关闭和打开高亮行列
    autocmd WinLeave * set nocul
    autocmd WinEnter * set cul

    "================================
    " => ALE配置
    "================================
    " 显示指定linters
    let g:ale_linters = {
          \   'cpp': ['clangtidy', 'cppcheck', 'gcc'],
          \   'c': ['gcc', 'cppcheck'],
          \   'sh': ['shell'],
          \}
    let g:ale_linters_explicit = 1
    let g:ale_sign_column_always = 1
    let g:ale_disable_lsp = 1
    let g:ale_completion_enabled = 0
    let g:ale_set_highlights = 1
    let g:ale_echo_msg_format = '[%linter%] %s  [%severity%]'
    let g:ale_lint_on_text_changed = 'never'
    let g:ale_lint_on_insert_leave = 1          " 只在离开插入模式才进行语法检测，按 <C-C> 离开插入模式可避免触发
    let g:ale_lint_on_enter = 0
    let g:ale_lint_on_save = 0
    let g:ale_c_gcc_options = '-Wall -Wextra -O2 -std=c11'
    let g:ale_c_cppcheck_options = '--enable=warning,style,performance,portability,information --std=c11'
    let g:ale_cpp_gcc_options = '-Wall -Wextra -O2 -std=c++17'
    let g:ale_cpp_cppcheck_options = '--enable=warning,style,performance,portability,information --std=c++17'
    let g:ale_cpp_clangtidy_options = '-extra-arg=-Weverything -extra-arg=-Wno-c++98-compat -extra-arg=-Wno-c++98-compat-pedantic -extra-arg=-Wno-pedantic -extra-arg=-Wno-missing-prototypes -extra-arg=-Wno-padded -extra-arg=-Wno-old-style-cast -extra-arg=-O2 -extra-arg=-std=c++17'
    let g:ale_sign_error = '✗'
    let g:ale_sign_warning = '‼'
    let g:ale_sign_info = '⚡'
    let g:ale_echo_msg_error_str = '✗'
    let g:ale_echo_msg_warning_str = '‼'
    let g:ale_echo_msg_info_str = '⚡'
    hi! clear SpellBad
    hi! clear SpellCap
    hi! clear SpellRare
    hi! SpellBad gui=undercurl guisp=red
    hi! SpellCap gui=undercurl guisp=yellow
    hi! SpellRare gui=undercurl guisp=magenta
    nnoremap <silent> gn :ALENextWrap<CR>
    nnoremap <silent> gb :ALEPreviousWrap<CR>
    let g:is_ALE_Running = 1
    function! ToggleALE()
        if g:is_ALE_Running == 1
            let g:is_ALE_Running = 0
            ALEToggle
            echo "ALE Disable!"
        else
            let g:is_ALE_Running = 1
            ALEToggle
            echo "ALE Enable!"
        endif
    endfunction
    nnoremap <silent> <space>a :call ToggleALE()<cr>

    "================================
    " => QuickRun配置
    "================================
    "该配置依赖quickrun_time程序，将仓库里的time.cpp编译后放到$PATH目录下即可
    "该配置限制了运行程序所使用的内存大小最大为500M
    "提供命令 :QuickrunArgs 设置传递给该例程的命令行参数
    "提供命令 :QuickrunRedirect 重定向该例程的stdin与stdout，使用：-i InputFile -o OutputFile
    let g:QuickRunArgs=''
    let g:QuickRunRedirect=''
    let g:QuickRunBufnr=0
    let g:QuickRun_PATH=''
    command! -nargs=1 QuickrunArgs let g:QuickRunArgs = <q-args>
    command! -nargs=1 QuickrunRedirect let g:QuickRunRedirect = <q-args>
    command! QuickInput execute 'let g:QuickRunRedirect = "-i /tmp/' . expand('%:r') . '.input"'
    function! QuickRun()
        if !isdirectory('/tmp/QuickRun')
            !mkdir /tmp/QuickRun
        endif
        if !isdirectory('/sys/fs/cgroup/memory/test')
            !sudo mkdir /sys/fs/cgroup/memory/test
        endif
        if g:QuickRunBufnr != 0 && bufexists(g:QuickRunBufnr)
            execute 'bd ' . g:QuickRunBufnr
        endif
        if &modified == 0 && g:QuickRun_PATH =~ expand('%:r')
            rightbelow 15 split
            execute 'term ++noclose ++norestore ++curwin sh -c "sudo sh -c \"echo $$ > /sys/fs/cgroup/memory/test/cgroup.procs\" && sudo sh -c \"echo 500M | tee /sys/fs/cgroup/memory/test/memory.memsw.limit_in_bytes > /sys/fs/cgroup/memory/test/memory.limit_in_bytes\"'
                        \ . ' && echo -e \"\\e[1;33mNote: Rerunning last compiled program!\\e[m\" && quickrun_time '
                        \ . g:QuickRunRedirect . ' ' . g:QuickRun_PATH . ' ' . g:QuickRunArgs . '"'
        else
            write
            rightbelow 15 split
            let QuickRun_TIME = strftime('%M%H')
            let QuickRun_FILE = expand('%:r')
            let g:QuickRun_PATH = '/tmp/QuickRun/' . QuickRun_FILE . '.' . QuickRun_TIME
            execute 'term ++noclose ++norestore ++curwin sh -c "sudo sh -c \"echo $$ > /sys/fs/cgroup/memory/test/cgroup.procs\" && sudo sh -c \"echo 500M | tee /sys/fs/cgroup/memory/test/memory.memsw.limit_in_bytes > /sys/fs/cgroup/memory/test/memory.limit_in_bytes\"'
                        \ ' && echo -e \"\\e[1;32m[Compile] ' . g:QuickRun_PATH .
                        \ '\\e[m\" && g++ -std=c++17 -O2 -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -I. -o ' . g:QuickRun_PATH . ' ' . expand('%') .
                        \ ' && quickrun_time ' . g:QuickRunRedirect . ' ' . g:QuickRun_PATH . ' ' . g:QuickRunArgs . '"'
        endif
        let g:QuickRunBufnr=bufnr('%')
        wincmd p
    endfunction
    " 按 <Space>lr 快速编译并运行当前Buffer的C++程序，按 <Space>lt 开关运行窗口，按 <Space>ld 快速编译当前程序用于gdb调试，按 <Space>li 快速打开输入窗口编辑测试输入并将运行的程序的stdin重定向到该文件
    nnoremap <silent> <space>lr :call QuickRun()<CR>
    nnoremap <silent> <space>lt :execute 'bd ' g:QuickRunBufnr<cr>
    nnoremap <silent> <space>ld :w<cr>:execute '!g++ -std=c++17 -Og -g3 -fno-inline -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -I. -o ' . expand('%:r') . ' ' . expand('%')<CR>
    nnoremap <silent> <space>lc :w<cr>:execute '!clang++ -std=c++17 -O3 -I. -o ' . expand('%:r') . ' ' . expand('%')<CR>
    autocmd BufLeave *.input :w
    nnoremap <silent> <space>li <c-w>v<c-w><right>30<c-w>\|:execute 'e /tmp/' . expand('%:r') . '.input'<cr>:wincmd p<cr>:QuickInput<cr>
    "function! QuickrunInput()
        "let g:QuickRunInputFile=expand('%:r')
        "normal '<c-w><right><c-w>s'
        "execute 'e /tmp/' . g:QuickRunInputFile . '.input'
        "wincmd p
        "QuickrunInput
    "endfunction

    "===============================
    " => 手动加载GVIM专用插件
    "===============================
    call plug#load('ale')

endif

